package com.library.admin.controller;

import cn.hutool.core.lang.Validator;
import com.library.admin.modules.user.bo.UserLoginBO;
import com.library.admin.modules.user.bo.UserSmsLoginBO;
import com.library.admin.modules.user.entity.User;
import com.library.admin.modules.user.service.UserService;
import com.library.common.constant.CacheTimeConstant;
import com.library.common.constant.Constants;
import com.library.common.constant.RedisKeyConstant;
import com.library.common.constant.VerificationCode;
import com.library.common.enums.ErrorCodeEnum;
import com.library.common.enums.LogTypeEnum;
import com.library.common.enums.StatusEnum;
import com.library.common.response.Result;
import com.library.common.util.FileUtils;
import com.library.common.util.RedisUtil;
import com.library.common.util.SmsUtil;
import com.library.logging.annotation.LogSys;
import com.wf.captcha.SpecCaptcha;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.awt.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author: xyh
 * @create: 2023-10-01
 **/
@Log4j2
@RestController
@RequestMapping("web")
public class LoginController {

    @Resource
    private RedisUtil redisUtil;
    @Resource
    private UserService userService;
    @Value("${jwt.tokenHead}")
    private String tokenHead;

    /**
     * 获取账号登录验证码
     *
     * @param
     * @return
     * @throws IOException
     */
    @GetMapping("/captcha")
    public Result getVerifyCode() throws IOException, FontFormatException {
        // 设置请求头为输出图片类型
        VerificationCode code = new VerificationCode();
        SpecCaptcha specCaptcha = code.createVerificationCode();
        String captchaCode = code.getCaptchaCode();
        // 创建字节数组输出流
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // 将验证码图片输出到字节数组输出流中
        specCaptcha.out(baos);
        // 将字节数组转换为 Base64 编码
        byte[] imageBytes = baos.toByteArray();
        String base64String = FileUtils.getBase64String(imageBytes);
        redisUtil.set(RedisKeyConstant.LOGIN_VERIFY_CODE + captchaCode, captchaCode, CacheTimeConstant.verifyCodeTime, TimeUnit.MINUTES);
        return Result.success("", base64String);
    }

    @RequestMapping("/hello")
    public String hello(){
        return "hello";
    }

    /**
     * 获取手机验证码
     *
     * @param bo
     * @return
     */
    @PostMapping("/sms/captcha")
    public Result getSmsVerifyCode(@Valid @RequestBody UserSmsLoginBO bo) {
        if (bo.getPhone() == null && !Validator.isMobile(String.valueOf(bo.getPhone()))) {
            return Result.error("手机号不能为空！");
        }
        String redisKey;
        if (Constants.ZERO.equals(bo.getCaptchaType())) {
            redisKey = RedisKeyConstant.SMS_VERIFY_REGISTER_CODE + bo.getPhone();
        } else {
            redisKey = RedisKeyConstant.SMS_VERIFY_FORGET_CODE + bo.getPhone();
        }
        Object object = redisUtil.get(redisKey);
        if (object != null) {
            return Result.error("验证码有效期在一分钟内，还未过期！");
        }
        if (Constants.ZERO.equals(bo.getCaptchaType())) {
            User userByPhone = userService.getUserByPhone(bo.getPhone());
            if (userByPhone != null) {
                return Result.error("手机号已经注册，可直接登录！");
            }
        }
        String smsCode = String.valueOf((int)((Math.random() * 9 + 1) * Math.pow(10,5)));
        try {
            SmsUtil.sendSms(String.valueOf(bo.getPhone()), smsCode);
            redisUtil.set(redisKey, smsCode, CacheTimeConstant.smsVerifyCodeTime, TimeUnit.MINUTES);
        } catch (Exception e) {
            log.error("短信验证码获取失败！", e);
            return Result.error("短信验证码获取失败，请重试或联系管理员！");
        }
        return Result.success();
    }


    /**
     * 账号登录
     *
     * @return token
     */
    @LogSys(value = "登录", logType = LogTypeEnum.LOGIN_SUCCESS)
    @PostMapping("/login")
    public Result<Object> login(@Valid @RequestBody UserLoginBO bo) {
        User user = userService.getUserByUsername(bo.getUsername());
        if (user == null) {
            return Result.error("您好，登录用户不存在，请联系管理员！");
        }
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        if (!bCryptPasswordEncoder.matches(bo.getPassword(), user.getPassword())) {
            return Result.error("用户密码不正确！");
        }
        if (StatusEnum.STOP.equals(user.getStatus())) {
            return Result.error(ErrorCodeEnum.USER_STOP.getCode(), "该帐号已被停用，无法登录");
        }
        //获取验证码
        String captchaCache = (String) redisUtil.get(RedisKeyConstant.LOGIN_VERIFY_CODE + bo.getVerifyCode());
        if (!userService.checkCode(captchaCache, bo.getVerifyCode())) {
            return Result.error(ErrorCodeEnum.VERIFY_CODE.getCode(), "验证码不正确或已过期");
        }
        String token = userService.login(bo);
        if (token == null) {
            return Result.error("用户名或密码错误");
        }
        Map<String, String> map = new HashMap<>(4);
        map.put("token", tokenHead + token);
        return Result.success(map);
    }

    /**
     * 退出登录
     *
     * @return
     */
    @LogSys(value = "退出", logType = LogTypeEnum.LOGIN_OUT)
    @GetMapping("/logout")
    public Result<Object> logout() {
        return Result.success("退出成功");
    }

}
